package se.sll.service.catalogue.composite.processor;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.ejb.Stateless;
import lombok.extern.slf4j.Slf4j;
import org.apache.camel.Exchange;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.JsonMappingException;
import riv.service.catalogue._2.CVType;
import riv.service.catalogue._2.CapacityType;
import riv.service.catalogue._2.CareUnitCapacityType;
import riv.service.catalogue._2.DatePeriodType;
import riv.service.catalogue._2.OfferType;
import riv.service.catalogue._2.OrganizationalUnitType;
import riv.service.catalogue._2.ProductCapacityType;
import riv.service.catalogue._2.ProductType;
import riv.service.catalogue._2.ResultType;
import riv.service.catalogue._2.SupportedInteractionsType;
import riv.service.catalogue.aggregated.enums._2.ResultCodeEnum;
import se.riv.service.catalogue.findoffersresponder.v2.FindOffersResponseType;
import se.riv.service.catalogue.getcapacitiesresponder.v1.GetCapacitiesResponseType;
import se.riv.service.catalogue.getproductsresponder.v2.GetProductsResponseType;
import se.riv.service.catalogue.pulloffersresponder.v1.PullOffersResponseType;
import se.sll.service.catalogue.capacity.api.model.Capacity;
import se.sll.service.catalogue.capacity.api.model.CareUnitRefList;
import se.sll.service.catalogue.capacity.api.model.Product;
import se.sll.service.catalogue.common.property.CatalogProperties;
import se.sll.service.catalogue.offers.api.model.Code;
import se.sll.service.catalogue.offers.api.model.OfferUnitList;
import se.sll.service.catalogue.offers.api.model.ProductReference;
import se.sll.service.catalogue.product.api.model.ProductList;

/**
 *
 * @author khaleddaham
 */
@Slf4j
@Stateless
public class RIVTAResponseProcessor {

    private static final String PRODUCT_CATALOGUE_OID = "oid.sll.product.catalogue";

    /**
     * Convert REST Product model to RIVTA Product Catalogue model
     *
     * @param exchange
     * @throws JsonParseException
     * @throws JsonMappingException
     * @throws IOException
     */
    public void fromProductToGetProducts(Exchange exchange) throws JsonParseException, JsonMappingException, IOException {
        GetProductsResponseType response = new GetProductsResponseType();
//        codeSystem.setCodeSystem(PRODUCT_CATALOGUE_OID);
        @SuppressWarnings("unchecked")
        List<ProductList> body = (List<ProductList>) exchange.getIn().getBody();
        for (ProductList restProduct : body) {
            ProductType wsProduct = new ProductType();
            CVType cv = new CVType();
            cv.setCode(restProduct.getName());
            cv.setCodeSystem(PRODUCT_CATALOGUE_OID);
            cv.setCodeSystemVersion(null);
            cv.setDisplayName(restProduct.getDisplayName());
//            wsProduct.set
//            wsProduct.setProductDescription(restProduct.getDescription());
//            wsProduct.setProductCode(cv);
//            codeSystem.getProduct().add(wsProduct);
        }
//        response.getProductCatalogue().add(codeSystem);
        ResultType resultType = new ResultType();
        resultType.setResultCode(ResultCodeEnum.OK);
        response.setResult(resultType);
        exchange.getIn().setBody(response);
    }

    /**
     * Convert REST Capacity model to RIVTA Capacity model
     *
     * @param exchange
     */
    public void fromCapacityToGetCapacities(Exchange exchange) {
        GetCapacitiesResponseType response = new GetCapacitiesResponseType();
        @SuppressWarnings("unchecked")
        List<CareUnitRefList> body = (List<CareUnitRefList>) exchange.getIn().getBody();
        for (CareUnitRefList restResponse : body) {
            CareUnitCapacityType ct = new CareUnitCapacityType();
            ct.setHSAId(restResponse.getHsaID());
            ct.setOrganizationName(restResponse.getHsaID());
            for (Product restProduct : restResponse.getProduct()) {
                ProductCapacityType p = new ProductCapacityType();
                CVType product = new CVType();
                product.setCode(restProduct.getName());
                product.setCodeSystem(CatalogProperties.getProperty(CatalogProperties.NAME.PRODUCT_OID));
                p.setProduct(product);
                for (Capacity restCapacity : restProduct.getCapacity()) {
                    CapacityType c = new CapacityType();
                    CVType cv = new CVType();
                    cv.setCode(restCapacity.getCode());
                    cv.setCodeSystem(CatalogProperties.getProperty(CatalogProperties.NAME.CAPACITY_OID));
                    cv.setDisplayName(this.getCapacityDisplayName(cv.getCode()));
                    c.setCode(cv);
                    c.setValidTo(new java.text.SimpleDateFormat("yyyyMMddHHmmss").format(c.getValidTo()));
                    c.setValue(restCapacity.getValue());
                    p.getCapacity().add(c);
                }
                ct.getProductCapacity().add(p);
            }
            response.getOrganizationalUnit().add(ct);
        }
        ResultType resultType = new ResultType();
        resultType.setResultCode(ResultCodeEnum.OK);
        response.setResult(resultType);
        exchange.getIn().setBody(response);
    }

    /**
     * Convert REST Offer and Product model to RIVTA Offers model.
     *
     * @param exchange
     */
    public void fromOfferToPullOffers(Exchange exchange) {
        @SuppressWarnings("unchecked")
        List<OfferUnitList> offerData = (List<OfferUnitList>) exchange.getProperty("offer");
        //List<ProductData> productData = (List<ProductData>) exchange.getIn().getBody();
        PullOffersResponseType response = new PullOffersResponseType();
        response.getOffer().addAll(buildOfferType(offerData, new ArrayList<se.sll.service.catalogue.offers.api.model.Product>()));
        ResultType resultType = new ResultType();
        resultType.setResultCode(ResultCodeEnum.OK);
        response.setResult(resultType);
        exchange.getIn().setBody(response);
    }

    /**
     * Convert REST Offer and Product model to RIVTA Offers model.
     *
     * @param exchange
     */
    @SuppressWarnings("unchecked")
    public void fromOfferToFindOffers(Exchange exchange) {
        List<OfferUnitList> offerData = (List<OfferUnitList>) exchange.getProperty("offer");
        List<se.sll.service.catalogue.offers.api.model.Product> productData = (List<se.sll.service.catalogue.offers.api.model.Product>) exchange.getIn().getBody();
        FindOffersResponseType response = new FindOffersResponseType();
        response.getOffer().addAll(buildOfferType(offerData, productData));
        ResultType resultType = new ResultType();
        resultType.setResultCode(ResultCodeEnum.OK);
        response.setResult(resultType);
        exchange.getIn().setBody(response);
    }

    /**
     *
     * @param offerData
     * @param productData
     * @return
     */
    private List<OfferType> buildOfferType(List<OfferUnitList> offerData, List<se.sll.service.catalogue.offers.api.model.Product> productData) {
        List<OfferType> offerTypeList = new ArrayList<>();
        for (OfferUnitList o : offerData) {
            OfferType e = new OfferType();
            OrganizationalUnitType careUnit = new OrganizationalUnitType();
            careUnit.setHSAId(o.getUnitId());
            careUnit.setOrganizationName("");
            careUnit.setPostalAddress("");
            e.setOrganizationalUnit(careUnit);
            //e.getSupportedInteraction().add(new SupportedInteractionsType());
            for (ProductReference pr : o.getProductReferences()) {
                ProductType p = new ProductType();
                p.setRequestComment("Remisskommentar");
                CVType cv = new CVType();
                cv.setCode(pr.getProduct().getName());
                for (se.sll.service.catalogue.offers.api.model.Product product : productData) {
                    if (product.getName().equals(pr.getProduct().getName())) {
                        cv.setDisplayName(product.getDisplayName());
                        p.setDescription(product.getDescription());
                        for (Code code : product.getCodes()) {
                            CVType prop = new CVType();
                            prop.setCode(code.getCode());
                            prop.setCodeSystem(code.getOid());
                            p.getProperty().add(prop);
                        }
                    }
                }
                cv.setCodeSystem(CatalogProperties.getProperty(CatalogProperties.NAME.PRODUCT_OID));
//                p.set
//                p.setProductId(cv);
                e.getProduct().add(p);
            }
            DatePeriodType dt = new DatePeriodType();
            dt.setStart("20000101");
            dt.setEnd("20200101");
            e.setValidContractDatePeriod(dt);
            offerTypeList.add(e);
        }
        return offerTypeList;
    }

    /**
     * @TODO this should be fetched/cached from the product catalogue.
     * @param code
     * @return
     */
    private String getCapacityDisplayName(String code) {
        if (code.equals("1")) {
            return "Väntetid mottagning";
        } else if (code.equals("2")) {
            return "Väntetid mottagning förtur";
        } else if (code.equals("3")) {
            return "Väntetid operation mottagning";
        } else if (code.equals("4")) {
            return "Väntetid operation mottagning förtur";
        } else if (code.equals("5")) {
            return "Väntetid operation";
        } else if (code.equals("6")) {
            return "Väntetid operation förtur";
        }
        return "";
    }
}
